package org.example.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.util.concurrent.ListenableFuture;
import org.example.entity.Employee;
import org.example.entity.StsTest;
import org.example.entity.TbCart;
import org.example.mapper.EmployeeMapper;
import org.example.service.IEmployeeService;
import org.example.service.IStsTestService;
import org.example.service.ITbCartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.*;

import static org.apache.commons.fileupload.FileUploadBase.CONTENT_TYPE;



/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author zhaowenting
 * @since 2024-04-08
 */
@RestController
@RequestMapping("/sts-test")
public class StsTestController {
    @Autowired
    IStsTestService iStsTestService;
    @Autowired
    ITbCartService iTbCartService;
    @Autowired
    IEmployeeService employeeService;

    @GetMapping("test")
    public Object aa() {
        Page<Employee> page = new Page<>();
        page.setCurrent(1);
        page.setSize(3);
        Page<Employee> selectPage = employeeService.page(page);
        return selectPage.getRecords();
    }

    @RequestMapping("exportExcel1")
    public void exportExcel1(HttpServletResponse response) throws InterruptedException, IOException {
        setExportHeader1(response);
        Integer count = iStsTestService.count();
        System.err.println("数量为："+count);
        Integer sheets = 20;
        Integer size = count / sheets;
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(sheets);
        CountDownLatch countDownLatch = new CountDownLatch(sheets);
        ConcurrentHashMap<Integer, Page<StsTest>> pageMap = new ConcurrentHashMap<>();

        for (int i = 0; i < sheets; i++) {
            int finalI = i;
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    Page<StsTest> page = new Page<>();
                    page.setCurrent(finalI + 1);
                    page.setSize(size);
                    Page<StsTest> selectPage = iStsTestService.page(page);
                    //System.err.println("456===="+selectPage.getRecords());
                    pageMap.put(finalI, selectPage);
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();//
        executorService.shutdown();
        //System.err.println("333====="+pageMap);
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), StsTest.class).build();

//            for(Map.Entry<Integer, Page<Employee>>entry : pageMap.entrySet()) {
//                Integer num = entry.getKey();
//                System.out.println("111===="+num);
//                Page<Employee> doPage = entry.getValue();
//                System.out.println("222===="+doPage.getRecords());
//                WriteSheet writeSheet = EasyExcel.writerSheet(num,"模板" + num).build();
//                excelWriter.write(doPage.getRecords(), writeSheet);
//            }
        pageMap.forEach((k, v) -> {
            final List<StsTest> records = v.getRecords();
            //System.out.println(records);
            WriteSheet writeSheet = EasyExcel.writerSheet(k, "模板" + k).build();
            excelWriter.write(records, writeSheet);

        });
        excelWriter.finish();
// 记录结束时间
        long endTime = System.currentTimeMillis();
        // 计算执行时间
        long executionTime = endTime - startTime;
        long len=executionTime/1000;
        System.out.println("执行时间：" + len + "s");
    }
    private static void setExportHeader1(HttpServletResponse response) {
        response.setContentType(CONTENT_TYPE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "test.xlsx");
    }

    /**
     *
     异步处理：可以方便地进行异步操作，并在后续处理异步操作的结果。
     组合操作：支持将多个异步操作组合在一起，以实现更复杂的异步流程。
     异常处理：能够方便地处理异步操作中可能出现的异常。
     回调机制：支持通过回调函数来处理操作的结果或异常。

     使用CompletableFuture可以提高程序的并发性能和响应性，使异步操作的处理更加简洁和高效。

     例如，可以使用CompletableFuture来执行数据库查询、网络请求等异步操作，并在操作完成后进行相应的处理。

     它是 Java 中处理异步操作的一种强大工具。如果你想了解更多关于CompletableFuture的具体使用方法和示例，可以查阅相关的 Java 文档和教程。
     * @param response
     * @throws InterruptedException
     * @throws IOException
     */
   @RequestMapping("exportExcel4")
   public void exportExcel4(HttpServletResponse response) throws InterruptedException, IOException {
       setExportHeader(response);
       Integer count = iStsTestService.count();
       System.err.println("数量为：" + count);
       Integer sheets = 20;
       Integer size = count / sheets;

       long startTime = System.currentTimeMillis();

       List<CompletableFuture<Page<StsTest>>> futures = new ArrayList<>();
       for (int i = 0; i < sheets; i++) {
           int finalI = i;
           CompletableFuture<Page<StsTest>> future = CompletableFuture.supplyAsync(() -> {
               Page<StsTest> page = new Page<>();
               page.setCurrent(finalI + 1);
               page.setSize(size);
               return iStsTestService.page(page);
           });
           futures.add(future);
       }

       CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
       allOf.join();

       ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), StsTest.class).build();
       futures.forEach(future -> {
           Page<StsTest> page = future.join();
           List<StsTest> records = page.getRecords();
           WriteSheet writeSheet = EasyExcel.writerSheet((int) (page.getCurrent() - 1), "模板" + (page.getCurrent() - 1)).build();
           excelWriter.write(records, writeSheet);
       });

       excelWriter.finish();

       long endTime = System.currentTimeMillis();
       long executionTime = endTime - startTime;
       long len = executionTime / 1000;
       System.out.println("执行时间：" + len + "s");
   }

    private static final String CONTENT_TYPE = "application/vnd.ms-excel";
    private static final String FILE_NAME = "test.xlsx";

    private static void setExportHeader(HttpServletResponse response) {
        response.setContentType(CONTENT_TYPE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + FILE_NAME);
    }


    /**
     * 普通excel导出
     */
    @RequestMapping("normalExcel")
    public void normalExcel(HttpServletResponse response) throws IOException {
        final long startTime = System.currentTimeMillis();
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        final List<StsTest> list = iStsTestService.list();
        EasyExcel.write(response.getOutputStream(), StsTest.class).sheet("模板").doWrite(list);
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        long len = executionTime / 1000;
        System.out.println("执行时间：" + len + "s");
    }

}



